Анализ и визуализация данных
Работа с DataFrames
Создание объекта типа DataFrame
Библиотека Julia DataFrames.jl предоставляет инструментарий для работы с табличными данными. Перед началом работы с библиотекой ее необходимо загрузить:
using DataFrames
Самым базовым типом в библиотеке DataFrames.jl является DataFrame (фрейм данных). Объекты типа DataFrame представляют таблицу данных в виде ряда векторов, каждый из которых соответствует столбцу или переменной. Обычно в нем каждая строка интерпретируется как наблюдение, а каждый столбец — как признак.
Многие фреймы данных организованы в соответствии со следующими принципами:
- В каждом столбце содержатся данные одинакового типа (текст, числа, логический тип и т.д.);
- Разные столбцы могут хранить данные разного типа (в отличие от матриц);
- Каждый столбец, как правило, имеет собственное уникальное название;
- В каждом столбце расположено одинаковое количество строк.
Самый простой способ построения DataFrame — это передача векторов столбцов с помощью именованных аргументов или пар. Например:
DataFrame(a=1:4, b=["A", "B", "C", "D"])
Рассмотрим примеры других часто используемых способов построения фреймов данных.
- Конструктор таблиц из именованного кортежа векторов:
DataFrame((a=[1, 2], b=[3, 4]))
- Конструктор таблиц из вектора именованных кортежей:
DataFrame([(a=1, b=3), (a=2, b=4)])
- Конструктор матриц:
DataFrame([1 2; 3 4], :auto)
Чтение данных из CSV-файлов
Рассмотрим один из наиболее распространенных сценариев, когда данные хранятся на диске в формате CSV.
Сначала необходимо загрузить библиотеку CSV.jl:
using CSV
В качестве примера рассмотрим файл datafile.csv, находящийся в папке данного курса. Для его чтения используем функцию CSV.read:
data = CSV.read("datafile.csv", DataFrame)
Обратите внимание, что DataFrames.jl выводит тип данных столбца под его именем. В данном случае это Int64 или Float64.
Чтение данных из XLSX-файлов
Если табличные данные хранятся в формате XLSX, то сначала нужно загрузить библиотеку XLSX.jl:
using XLSX
Для считывания файла EPLresults.xlsx, находящегося в папке данного курса, воспользуемся функцией XLSX.readtable.
EPL = DataFrame(XLSX.readtable("EPLresults.xlsx", "Sheet1"))
Здесь "Sheet1" — имя первого листа данного файла. Даже если файл состоит из одного листа, все равно имя листа необходимо указывать в качестве второго аргумента функции XLSX.readtable.
В этой таблице содержатся результаты выступлений команд английской футбольной Премьер-лиги в сезоне 2015–2016 гг. В таблице есть текстовая информация (названия столбцов) и численные данные. Столбцы таблицы означают следующее:
Team— название команды;HomeWins— число побед в домашних матчах;HomeDraws— число ничьих в домашних матчах;HomeLosses— число поражений в домашних матчах;HomeGF— число голов, забитых в домашних матчах;HomeGA— число голов, пропущенных в домашних матчах;AwayWins— число побед в матчах на выезде;AwayDraws— число ничьих в матчах на выезде;AwayLosses— число поражений в матчах на выезде;AwayGF— число голов, забитых в матчах на выезде;AwayGA— число голов, пропущенных в матчах на выезде.
Основные операции с фреймами данных
С помощью функции Matrix можно преобразовать фрейм EPL в матрицу:
Matrix(EPL)
Чтобы извлечь столбцы фрейма данных напрямую (то есть без копирования), можно воспользоваться одной из следующих синтаксических конструкций: EPL.Team, EPL."team", EPL[!, :Team] или EPL[!, "Team"].
EPL.Team
✏️Задание 1
Выведите на экран столбец HomeWins таблицы EPL.
Подсказка
К столбцу таблицы можно обратиться как к полю объекта, через точку: ИмяТаблицы.ИмяСтолбца.
Решение
EPL.HomeWins
Получить вектор имен столбцов фрейма данных в виде строк можно с помощью функции names(EPL).
✏️Задание 2
Выведите на экран названия всех столбцов таблицы EPL.
Подсказка
Воспользуйтесь функцией names. В качестве аргумента функции задайте имя таблицы.
Решение
names(EPL)
Функция size возвращает размерность фрейма данных:
size(EPL)
С помощью функций nrow и ncol можно получить отдельно количество строк и столбцов во фрейме данных:
nrow(EPL)
ncol(EPL)
Для получения базовой статистики по данным во фрейме данных используйте функцию describe. По умолчанию выводятся такие статистические показатели, как среднее, минимальное, медианное и максимальное значения, количество отсутствующих значений и тип элементов столбца.
describe(EPL)
Получение и изменение данных во фрейме данных
Фрейм данных может индексироваться так же, как матрица. Синтаксис индексирования имеет общий вид data_frame[selected_rows, selected_columns]. Обратите внимание, что, в отличие от матриц, необходимо обязательно передавать как селектор строк, так и селектор столбцов. Двоеточие : указывает на то, что все элементы (строки или столбцы в зависимости от позиции) должны сохраняться. Вот несколько примеров:
EPL[1:5, :HomeWins]
EPL[5:10, :]
EPL[:, [:HomeWins, :HomeDraws, :HomeLosses]]
Чтобы получить одну ячейку фрейма данных, используйте тот же синтаксис, что и для получения элемента матрицы:
EPL[3, 5]
Выбранной ячейке можно присвоить новое значение так же, как и для элемента матрицы:
EPL[3, 5] = 30
Вернем этой ячейке исходное значение:
EPL[3, 5] = 23
✏️Задание 3
Присвойте значение 7 элементу таблицы EPL, находящемуся в пятой строке и третьем столбце. Затем выведите на экран обновленную таблицу.
Решение
EPL[5,3] = 7
display(EPL)
Можно создать новый столбец фрейма, присвоив ему какие-либо значения:
EPL.New_Column = collect([1:20;])
✏️Задание 4
Создайте таблицу top5, в которой будут содержаться столбцы для первых пяти команд из исходной таблицы EPL, содержащие название команды, количество домашних побед, домашних ничьих и домашних поражений.
Подсказка
Сначала сформируйте вектор v, содержащий четыре столбца: Team, HomeWins, HomeDraws и HomeLosses. Затем присвойте переменной top5 элементы таблицы EPL, содержащиеся в строках в диапазоне 1:5 и в столбцах, заданных вектором v, т.е. EPL[1:5, v].
Решение
v = ["Team", "HomeWins", "HomeDraws", "HomeLosses"];
top5 = EPL[1:5, v]
✏️Задание 5
Добавьте в таблицу EPL столбец Points, который будет содержать количество очков, набранных каждой командой. За каждую победу команде начисляется 3 очка, за каждую ничью — 1 очко.
Подсказка
Сначала нужно найти число побед для каждой команды. Оно складывается из числа побед в домашних и в выездных матчах, т.е. wins = EPL.HomeWins + EPL.AwayWins. Затем найдите число ничьих, сложив число ничьих в домашних и в выездных матчах: draws = EPL.HomeDraws + EPL.AwayDraws. Затем найдите число очков по формуле: EPL.Points = 3*wins + draws. Наконец, выведите на экран обновленную таблицу EPL.
Решение
wins = EPL.HomeWins + EPL.AwayWins
draws = EPL.HomeDraws + EPL.AwayDraws
EPL.Points = 3*wins + draws
print(EPL)
✏️Задание 6
Добавьте в таблицу EPL столбец GD, который будет содержать разность между забитыми и пропущенными голами для каждой команды.
Подсказка
Разность между забитыми и пропущенными голами EPL.GD вычисляется так: найдите сумму голов, забитых в домашних и в выездных матчах (EPL.HomeGF+EPL.AwayGF), и вычтите из нее сумму голов, пропущенных в домашних и в выездных матчах (EPL.HomeGA+EPL.AwayGA).
Решение
EPL.GD = EPL.HomeGF + EPL.AwayGF - (EPL.HomeGA + EPL.AwayGA)
print(EPL)
Выбор элементов из фрейма
-
select— создает фрейм данных с тем же количеством строк, что и в исходном фрейме данных, заполняя его столбцами, которые являются результатом преобразования столбцов исходного фрейма данных. -
select!— действует аналогичноselect, но изменяет переданный фрейм данных на месте.
Например, выберем из фрейма EPL столбцы, отражающие статистику выездных матчей:
select(EPL, 7:9)
✏️Задание 7
Выберите из таблицы EPL только те столбцы, которые отражают статистику домашних матчей (с 1-го по 6-й).
Подсказка
Воспользуйтесь функцией select. В качестве аргументов функции задайте имя таблицы и диапазон номеров столбцов с помощью оператора :.
Решение
select(EPL, 1:6)
Сортировка данных
sort— сортировка данных по выбранному столбцу. По умолчанию эта операция выстраивает строки таблицы в соответствии с возрастающими значениями ключей сортировки.
Например, отсортируем данные по числу поражений в домашних матчах:
sort(EPL, "HomeLosses")
Чтобы получить обратный порядок значений, нужно добавить в команду аргумент rev=true:
sort(EPL, "HomeLosses", rev=true)
sort!— отличается от функцииsortтем, что результат сортировки помещается в ту же самую переменную, откуда мы брали исходные данные для операции.
✏️Задание 8
Отсортируйте данные таблицы EPL по числу побед в домашних матчах.
Подсказка
Воспользуйтесь функцией sort. Аргументами функции являются исходная таблица EPL и имя столбца HomeWins.
Решение
sort(EPL, "HomeWins")
✏️Задание 9
Отсортируйте данные таблицы EPL по числу побед в домашних матчах так, чтобы результат сортировки записался в ту же самую переменную EPL.
Подсказка
Воспользуйтесь функцией sort!.
Решение
sort!(EPL, "HomeWins")
✏️Задание 10
Отсортируйте в обратном порядке данные таблицы EPL по числу побед в домашних матчах так, чтобы результат сортировки записался в ту же самую переменную EPL.
Подсказка
Воспользуйтесь функцией sort!. Добавьте в функцию третий аргумент rev=true.
Решение
sort!(EPL, "HomeWins", rev=true)
Сохранение фрейма данных
Чтобы поместить таблицу в файл, можно воспользоваться одним из следующих методов:
using CSV
CSV.write("EPL_output.csv", EPL)
или
using XLSX
XLSX.writetable( "EPL_output.xlsx", EPL)